# views.py
from collections import defaultdict
from datetime import timedelta

from django.db.models import Sum, Q, F, Min
from django.utils.datetime_safe import datetime
from rest_framework.mixins import ListModelMixin
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from staging.pagination import MyPagination
from utils.common_response import APIResponse
from .models import Product, SalesRecord, Inventory
from .serializers import ProductReportSerializer, DishReportSerializer, \
    PurchaseAmountQuantitySerializer, SaleAmountQuantitySerializer, InventoryTrendSerializer, SalesTrendSerializer
from django.utils import timezone


class ProductReportView(ListModelMixin, GenericViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductReportSerializer
    authentication_classes = []  # 局部禁用
    permission_classes = []
    throttle_classes = []
    pagination_class = MyPagination  # 选择分页类

    def get_queryset(self):
        queryset = super().get_queryset()
        created_at = self.request.query_params.get('created_at')
        team_id = self.request.headers.get('team')  # 获取请求头中的门店ID
        category_id = self.request.query_params.get('category_id', None)

        if created_at:
            # 如果日期字符串不为空，则解析日期字符串成为datetime对象，并过滤记录
            self.created_at = timezone.datetime.strptime(created_at, '%Y-%m-%d')
        else:
            # 如果日期字符串为空，则设置为今天的日期
            self.created_at = timezone.now()

        # 获取库存表中符合条件的货品 ID 列表
        product_ids = Inventory.objects.filter(stock_in_time__date=self.created_at,
                                               stock_out_quantity__isnull=True,  # stock_out_quanitiy 为 None
                                               product_price__isnull=False,  # product_price 不为 None
                                               ).values_list('product_id', flat=True)

        # 根据货品 ID 列表过滤货品列表
        queryset = queryset.filter(product_id__in=product_ids)

        # 构建基础查询集
        if category_id:
            queryset = queryset.filter(category=category_id)
        # print(team_id)
        if team_id:
            # 根据门店ID过滤查询结果
            queryset = queryset.filter(team=team_id)
        print('视图类过滤完的:', queryset)
        return queryset.order_by('-created_at')  #

    def get_serializer_context(self):
        context = super().get_serializer_context()
        # 将 created_at 添加到 context 字典中
        context['created_at'] = self.created_at
        # 将过滤后的产品列表添加到 context 字典中
        # context['filtered_products'] = self.get_queryset()
        return context

    def list(self, request, *args, **kwargs):
        res = super().list(request, *args, **kwargs)
        return APIResponse(data=res.data)


class DishReportView(ListModelMixin, GenericViewSet):
    queryset = SalesRecord.objects.all()
    serializer_class = DishReportSerializer
    authentication_classes = []  # 局部禁用
    permission_classes = []
    throttle_classes = []
    pagination_class = MyPagination  # 选择分页类

    """
    先在视图集根据菜品时间，类别，门店去跨表去菜品表过滤需要的菜品销售查询集，
    然后在序列化器对每个对象返回的值进行定制
    """

    def get_queryset(self):
        queryset = super().get_queryset()
        created_at = self.request.query_params.get('created_at')
        team_id = self.request.headers.get('team')  # 获取请求头中的门店ID
        category_id = self.request.query_params.get('category_id', None)

        if created_at:
            # 如果日期字符串不为空，则解析日期字符串成为datetime对象，并过滤记录
            self.created_at = timezone.datetime.strptime(created_at, '%Y-%m-%d')
            queryset = queryset.filter(created_at__date=self.created_at.date())
        else:
            # 如果日期字符串为空，则设置为今天的日期
            self.created_at = timezone.now()
            queryset = queryset.filter(created_at__date=self.created_at.date())

            # 获取每个菜品对应的货品中当前库存表距离当前时间最近的数据的库存量
        queryset = queryset.annotate(min_stock=Min('dish__products__inventory__current_stock'))

        # 构建基础查询集
        if category_id:
            queryset = queryset.filter(dish__category_id=category_id)
        print(team_id)
        if team_id:
            # 根据门店ID过滤查询结果
            queryset = queryset.filter(dish__team_id=team_id)
        print('过完的销售记录', queryset)
        # 根据当前库存量最小的数量进行排序
        queryset = queryset.order_by(F('min_stock'))
        return queryset

    def get_serializer_context(self):
        context = super().get_serializer_context()
        # 将 created_at 添加到 context 字典中
        context['created_at'] = self.created_at
        return context

    def list(self, request, *args, **kwargs):
        res = super().list(request, *args, **kwargs)
        return APIResponse(data=res.data)


class PurchaseAmountQuantityView(ListModelMixin, GenericViewSet):
    queryset = Inventory.objects.all()
    serializer_class = PurchaseAmountQuantitySerializer
    authentication_classes = []  # 局部禁用
    permission_classes = []
    throttle_classes = []
    pagination_class = MyPagination  # 选择分页类

    def get_queryset(self):
        queryset = super().get_queryset()
        created_at = self.request.query_params.get('created_at')
        team_id = self.request.headers.get('team')  # 获取请求头中的门店ID

        if created_at:
            # 如果日期字符串不为空，则解析日期字符串成为datetime对象，并过滤记录
            self.created_at = timezone.datetime.strptime(created_at, '%Y-%m-%d')
        else:
            # 如果日期字符串为空，则设置为今天的日期
            self.created_at = timezone.now()

        if team_id:
            # 使用关联查询过滤查询结果
            queryset = queryset.filter(Q(product__team=team_id))

        return queryset.order_by('-created_at')  #

    def get_serializer_context(self):
        context = super().get_serializer_context()
        # 将 created_at 添加到 context 字典中
        context['created_at'] = self.created_at
        return context

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        serializer_context = self.get_serializer_context()
        serializer = self.serializer_class(context=serializer_context, instance=queryset)

        # 获取序列化器的计算结果
        data = serializer.data
        return APIResponse(data=data)


class SaleAmountQuantityView(ListModelMixin, GenericViewSet):
    queryset = SalesRecord.objects.all()
    serializer_class = SaleAmountQuantitySerializer
    authentication_classes = []  # 局部禁用
    permission_classes = []
    throttle_classes = []
    pagination_class = MyPagination  # 选择分页类

    def get_queryset(self):
        queryset = super().get_queryset()
        created_at = self.request.query_params.get('created_at')
        team_id = self.request.headers.get('team')  # 获取请求头中的门店ID

        if created_at:
            # 如果日期字符串不为空，则解析日期字符串成为datetime对象，并过滤记录
            self.created_at = timezone.datetime.strptime(created_at, '%Y-%m-%d')
        else:
            # 如果日期字符串为空，则设置为今天的日期
            self.created_at = timezone.now()

        if team_id:
            print(team_id)
            # 使用关联查询过滤查询结果
            queryset = queryset.filter(Q(dish__team=team_id))
            print(queryset)

        return queryset.order_by('-created_at')  #

    def get_serializer_context(self):
        context = super().get_serializer_context()
        # 将 created_at 添加到 context 字典中
        context['created_at'] = self.created_at
        return context

    def list(self, request, *args, **kwargs):

        queryset = self.filter_queryset(self.get_queryset())
        serializer_context = self.get_serializer_context()
        serializer = self.serializer_class(context=serializer_context, instance=queryset)

        # 获取序列化器的计算结果
        data = serializer.data
        return APIResponse(data=data)


class InventoryTrendView(ListModelMixin, GenericViewSet):
    queryset = Inventory.objects.all()
    serializer_class = InventoryTrendSerializer
    authentication_classes = []  # 局部禁用
    permission_classes = []
    throttle_classes = []
    pagination_class = MyPagination  # 选择分页类

    def get_queryset(self):
        queryset = super().get_queryset()

        # 获取查询参数
        period = self.request.query_params.get('period')
        price_type = self.request.query_params.get('price_type')
        product_name = self.request.query_params.get('product_name')  # 获取货品名称

        # 根据单个货品，可能今天进货了，隔几天都没有进货这种情况
        # 初始化结果字典
        product_prices = {}

        # 根据查询参数进行处理
        if period == 'week':
            today = datetime.now()
            print(today)
            # print(timedelta(days=today.weekday() + 6))
            print(today.weekday() + 1)
            start_date = today - timedelta(days=6)
            while start_date <= today:
                print(start_date.strftime('%m-%d'), start_date.strftime('%A'))
                # 查询当天的库存记录
                if price_type == 'total_price':
                    current_month = start_date.month
                    current_year = start_date.year
                    # 如果 price_type 是 'total_price'，直接获取当天所有产品的总价
                    inventory_item = \
                        queryset.filter(stock_in_time__date=start_date,
                                        product__name=product_name)
                    # 如果存在记录，获取对应的产品价格
                    if inventory_item.exists():
                        print(inventory_item)
                        # product_prices[start_date.strftime('%m-%d')] = inventory_item.latest(
                        #     'created_at').product_price
                        # inventory_item = inventory_item.latest('created_at')
                        # product = inventory_item.product
                        # 如果存在记录，获取对应的产品价格总和
                        total_purchase_amount = 0.0
                        for item in inventory_item:
                            product = item.product
                            if product and product.unit.name != '克' and product.unit.unit_type == 2:
                                purchase_amount = float(item.product_price) * float(item.before_weight) * float(
                                    item.quantity)
                            else:
                                purchase_amount = float(item.product_price) * float(item.quantity)
                            total_purchase_amount += purchase_amount
                        product_prices[start_date.strftime('%m-%d')] = total_purchase_amount
                    else:
                        # 否则按照货品名过滤记录，获取对应的产品价格
                        inventory_records = queryset.filter(product__name=product_name, stock_in_time__date=start_date)

                        # 如果存在记录，获取对应的产品价格
                        if inventory_records.exists():
                            product_prices[start_date.strftime('%m-%d')] = inventory_records.latest(
                                'created_at').product_price
                        else:
                            product_prices[start_date.strftime('%m-%d')] = None
                else:
                    # start_date += timedelta(days=1)
                    # 查询当天的库存记录
                    # 查询当天的库存记录
                    inventory_records = queryset.filter(product__name=product_name, stock_in_time__date=start_date)

                    try:
                        # 如果存在记录，获取对应的产品价格
                        if inventory_records.exists():
                            product_prices[start_date.strftime('%m-%d')] = inventory_records.latest(
                                'created_at').product_price
                        else:
                            # 查询离今天最近的前一天的数据
                            previous_inventory_record = queryset.filter(product__name=product_name,
                                                                        stock_in_time__date__lt=start_date).order_by(
                                '-stock_in_time').first()
                            product_prices[start_date.strftime('%m-%d')] = previous_inventory_record.product_price
                    except AttributeError:
                        # 前面为null的价格为最新价格
                        null_price = queryset.filter(product__name=product_name).latest(
                            'stock_in_time').product_price
                        if null_price:
                            # 如果发生错误，说明没有找到前一天的数据，则将价格设置为 None 或其他默认值
                            product_prices[start_date.strftime('%m-%d')] = null_price  # 或者设置为其他默认值
                        else:
                            # 如果没有找到前一天的数据，则将价格设置为 None
                            product_prices[start_date.strftime('%m-%d')] = None

                # 递增日期
                start_date += timedelta(days=1)
        elif period == 'month':
            # 计算当前月份的日期范围
            today = datetime.now()
            start_date = today - timedelta(days=30)

            # 遍历日期范围
            while start_date <= today:
                print(start_date.strftime('%m-%d'), start_date.strftime('%A'))
                # 查询当天的库存记录
                if price_type == 'total_price':
                    # 如果 price_type 是 'total_price'，直接获取当天所有产品的总价
                    inventory_item = \
                        queryset.filter(stock_in_time__date=start_date,
                                        product__name=product_name)
                    # 如果存在记录，获取对应的产品价格
                    if inventory_item.exists():
                        # product_prices[start_date.strftime('%m-%d')] = inventory_item.latest(
                        #     'created_at').product_price
                        # inventory_item = inventory_item.latest('created_at')
                        # product = inventory_item.product
                        # 如果存在记录，获取对应的产品价格总和
                        total_purchase_amount = 0.0
                        for item in inventory_item:
                            product = item.product
                            if product and product.unit.name != '克' and product.unit.unit_type == 2:
                                purchase_amount = float(item.product_price) * float(item.before_weight) * float(
                                    item.quantity)
                            else:
                                purchase_amount = float(item.product_price) * float(item.quantity)
                            total_purchase_amount += purchase_amount
                        product_prices[start_date.strftime('%m-%d')] = total_purchase_amount
                    else:
                        product_prices[start_date.strftime('%m-%d')] = None
                else:
                    # 否则按照货品名过滤记录，获取对应的产品价格
                    inventory_records = queryset.filter(product__name=product_name, stock_in_time__date=start_date)

                    try:
                        # 如果存在记录，获取对应的产品价格
                        if inventory_records.exists():
                            product_prices[start_date.strftime('%m-%d')] = inventory_records.latest(
                                'created_at').product_price
                        else:
                            # 查询离今天最近的前一天的数据
                            previous_inventory_record = queryset.filter(product__name=product_name,
                                                                        stock_in_time__date__lt=start_date).order_by(
                                '-stock_in_time').first()
                            product_prices[start_date.strftime('%m-%d')] = previous_inventory_record.product_price
                    except AttributeError:
                        # 前面为null的价格为最新价格
                        null_price = queryset.filter(product__name=product_name).latest(
                            'stock_in_time').product_price
                        if null_price:
                            # 如果发生错误，说明没有找到前一天的数据，则将价格设置为 None 或其他默认值
                            product_prices[start_date.strftime('%m-%d')] = null_price  # 或者设置为其他默认值
                        else:
                            # 如果没有找到前一天的数据，则将价格设置为 None
                            product_prices[start_date.strftime('%m-%d')] = None

                # 递增日期
                start_date += timedelta(days=1)
            # print(product_prices)

        return product_prices

    def list(self, request, *args, **kwargs):
        product_prices = self.filter_queryset(self.get_queryset())

        # if not queryset.exists():  # 如果 queryset 为空
        #     # 返回一个包含空数据的字典，以及一个标志来指示数据为空
        #     data = {'code': 100, 'msg': '获取数据成功', 'data': []}
        #     return Response(data)  # 返回 HTTP 204 状态码表示无内容
        # else:
        serializer_context = self.get_serializer_context()
        serializer = self.serializer_class(context=serializer_context, instance=product_prices)
        get_data = serializer.data
        data = {'code': 100, 'msg': '获取数据成功', 'data': get_data}
        return Response(data)


class SalesTrendView(ListModelMixin, GenericViewSet):
    queryset = SalesRecord.objects.all()
    serializer_class = SalesTrendSerializer
    authentication_classes = []  # 局部禁用
    permission_classes = []
    throttle_classes = []
    pagination_class = MyPagination  # 选择分页类

    def get_queryset(self):
        queryset = super().get_queryset()

        # 获取查询参数
        period = self.request.query_params.get('period')
        dish_name = self.request.query_params.get('dish_name')  # 获取货品名称
        price_type = self.request.query_params.get('price_type')

        # 初始化结果字典
        dish_prices = {}

        # 根据查询参数进行处理
        if period == 'week':
            today = datetime.now()
            print(today)
            # print(timedelta(days=today.weekday() + 6))
            print(today.weekday() + 1)
            start_date = today - timedelta(days=6)
            while start_date <= today:
                print(start_date.strftime('%m-%d'), start_date.strftime('%A'))
                # 查询当天的库存记录
                if price_type == 'total_price':
                    # 如果 price_type 是 'total_price'，直接获取当天所有产品的总价
                    total_price = \
                        queryset.filter(created_at__date=start_date).aggregate(total_price=Sum('dish_price'))[
                            'total_price']
                    dish_prices[start_date.strftime('%m-%d')] = total_price

                else:
                    # 否则按照货品名过滤记录，获取对应的产品价格
                    sale_records = queryset.filter(dish__name=dish_name, created_at__date=start_date)

                    try:
                        # 如果存在记录，获取对应的产品价格
                        if sale_records.exists():
                            dish_prices[start_date.strftime('%m-%d')] = sale_records.latest(
                                'created_at').dish_price
                        else:
                            # 查询离今天最近的前一天的数据
                            previous_sale_record = queryset.filter(dish__name=dish_name,
                                                                   created_at__date__lt=start_date).order_by(
                                '-created_at').first()
                            dish_prices[start_date.strftime('%m-%d')] = previous_sale_record.dish_price
                    except AttributeError:
                        # 前面为null的价格为最新价格
                        null_price = queryset.filter(dish__name=dish_name).latest(
                            'created_at').dish_price
                        if null_price:
                            # 如果发生错误，说明没有找到前一天的数据，则将价格设置为 None 或其他默认值
                            dish_prices[start_date.strftime('%m-%d')] = null_price  # 或者设置为其他默认值
                        else:
                            # 如果没有找到前一天的数据，则将价格设置为 None
                            dish_prices[start_date.strftime('%m-%d')] = None

                # 递增日期
                start_date += timedelta(days=1)
            print(dish_prices)
            # queryset = queryset.filter(created_at__date__range=[start_date, end_date])
        elif period == 'month':
            # 计算当前月份的日期范围
            today = datetime.now()
            start_date = today - timedelta(days=30)

            # 遍历日期范围
            while start_date <= today:
                print(start_date.strftime('%m-%d'), start_date.strftime('%A'))
                # 查询当天的库存记录
                if price_type == 'total_price':
                    # 如果 price_type 是 'total_price'，直接获取当天所有产品的总价
                    total_price = \
                        queryset.filter(created_at__date=start_date).aggregate(total_price=Sum('dish_price'))[
                            'total_price']
                    dish_prices[start_date.strftime('%m-%d')] = total_price
                else:
                    # 否则按照货品名过滤记录，获取对应的产品价格
                    sale_records = queryset.filter(dish__name=dish_name, created_at__date=start_date)

                    try:
                        # 如果存在记录，获取对应的产品价格
                        if sale_records.exists():
                            dish_prices[start_date.strftime('%m-%d')] = sale_records.latest(
                                'created_at').dish_price
                        else:
                            # 查询离今天最近的前一天的数据
                            previous_sale_record = queryset.filter(dish__name=dish_name,
                                                                   created_at__date__lt=start_date).order_by(
                                '-created_at').first()
                            dish_prices[start_date.strftime('%m-%d')] = previous_sale_record.dish_price
                    except AttributeError:
                        # 前面为null的价格为最新价格
                        null_price = queryset.filter(dish__name=dish_name).latest(
                            'created_at').dish_price
                        if null_price:
                            # 如果发生错误，说明没有找到前一天的数据，则将价格设置为 None 或其他默认值
                            dish_prices[start_date.strftime('%m-%d')] = null_price  # 或者设置为其他默认值
                        else:
                            # 如果没有找到前一天的数据，则将价格设置为 None
                            dish_prices[start_date.strftime('%m-%d')] = None

                # 递增日期
                start_date += timedelta(days=1)
        return dish_prices

    def list(self, request, *args, **kwargs):
        dish_prices = self.filter_queryset(self.get_queryset())

        # if not queryset.exists():  # 如果 queryset 为空
        #     # 返回一个包含空数据的字典，以及一个标志来指示数据为空
        #     data = {'code': 100, 'msg': '获取数据成功', 'data': []}
        #     return Response(data)  # 返回 HTTP 204 状态码表示无内容
        # else:
        serializer_context = self.get_serializer_context()
        serializer = self.serializer_class(context=serializer_context, instance=dish_prices)
        get_data = serializer.data
        data = {'code': 100, 'msg': '获取数据成功', 'data': get_data}
        return Response(data)
